package org.f0rb.demo.dao;

import org.f0rb.core.web.WebModel;

import java.util.*;

/**
 * Class org.f0rb.demo.mail description goes here.
 *
 * @author Yuan Zhen
 * @version 1.0.0 11-11-17
 */
public abstract class MapDAOImpl<T extends MapDAOImpl.DBMap> extends HibernateDAOImpl<T> implements MapDAO<T> {
    private Map<String, String> map = new HashMap<>();

    public MapDAOImpl(Class<T> entityClass) {
        super(entityClass);
    }

    protected void initDao() {
        readData();
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    @Override
    public String get(Object key) {
        if (!map.containsKey(key)) {
            T t = uniqueByProperty("key", key);
            if (t != null) {
                map.put(t.getKey(), t.getValue());
            }
        }
        return map.get(key);
    }

    protected abstract T getModelInstance(String key, String value);

    @Override
    public String put(String key, String value) {
        T t = getModelInstance(key, value);
        if (containsKey(key)) {
            update(t);
        } else {
            save(t);
        }
        return map.put(key, value);
    }

    @Override
    public String remove(Object key) {
        String value = map.remove(key);
        if (value != null) {
            delete(getModelInstance((String) key, value));
        }
        return value;
    }

    @Override
    public void putAll(Map<? extends String, ? extends String> m) {
        map.putAll(m);
    }

    @Override
    public void clear() {
        map.clear();
    }

    @Override
    public Set<String> keySet() {
        return map.keySet();
    }

    @Override
    public Collection<String> values() {
        return map.values();
    }

    @Override
    public Set<Entry<String, String>> entrySet() {
        return map.entrySet();
    }

    private void readData() {
        if (map.size() < super.size()) {
            map.clear();
            List<T> all = listAll();
            for (T t : all) {
                map.put(t.getKey(), t.getValue());
            }
        }
    }

    @Override
    public List<T> list() {
        return listAll();
    }

    /**
     * Class org.f0rb.demo.mail description goes here.
     *
     * @author Yuan Zhen
     * @version 1.0.0 11-11-17
     */
    public abstract static class DBMap<T extends DBMap<?>> extends WebModel<T> implements Entry<String, String> {
        protected DBMap() {
        }

        protected DBMap(String k, String v) {
            key = k;
            value = v;
        }

        /*protected DBMap(Class<T> clazz) {
        }

        protected DBMap(Class<T> clazz, String k, String v) {
            key = k;
            value = v;
        }*/

        public String key;
        public String value;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getValue() {
            return value;
        }

        public String setValue(String value) {
            this.value = value;
            return value;
        }

        @Override
        public T fillInModel(T map) {
            map.key = key;
            map.value = value;
            return map;
        }

        @Override
        public void fillByModel(T map) {
            key = map.key;
            value = map.value;
        }

        @Override
        public String toString() {
            return String.format("%s=%s", key, value);
        }
    }
}
